/**
  @author: cilang
  @qq: 1019383856
  @bili: https://space.bilibili.com/433915419
  @gitee: https://gitee.com/OpencvLZG
  @since: 4/3/2023
  @desc: //TODO
**/

package controller

import (
	"encoding/json"
	"github.com/gin-gonic/gin"
	"github.com/gorilla/websocket"
	"log"
	"time"
)

type (
	ChatController struct {
	}
)

type SenderMsg struct {
	Sender   int64
	Receptor int64
	Msg      string
	MsgType  string `data:"[notice,normal]"`
}

var Hub = make(map[int64]*websocket.Conn)

var MessageQueues = make(map[int64][]*SenderMsg)

var upgrader = websocket.Upgrader{
	ReadBufferSize:  1024,
	WriteBufferSize: 1024,
}

// WsHandle ws处理
func (c *ChatController) WsHandle(gc *gin.Context) {
	userController := new(UserController)
	user, err := userController.GetUserInfo(gc)
	if err != nil {
		return
	}
	wsConn, err := upgrader.Upgrade(gc.Writer, gc.Request, nil)
	if err != nil {
		log.Println(err)
	}
	Hub[user.Id] = wsConn
	go c.GetMessageQueue(wsConn, user.Id)
	go c.ChatWithUid(wsConn, user.Id)
}

// GetMessageQueue 用户上线获取消息队列
func (c *ChatController) GetMessageQueue(wsConn *websocket.Conn, userId int64) {
	defer func(wsConn *websocket.Conn) {
		wsConn.CloseHandler()
	}(wsConn)
	_, ok := MessageQueues[userId]
	if ok {
		// 消息队列处理
		timeStamp := time.Now().Add(time.Second * 10).Unix()
		for len(MessageQueues[userId]) > 0 {
			// 超时处理
			if timeStamp < time.Now().Unix() {
				break
			}
			// 出栈
			senderMsg := MessageQueues[userId][0]
			MessageQueues[userId] = MessageQueues[userId][1:]
			// 解码
			senderBytes, _ := json.Marshal(senderMsg)
			// 发送
			err := wsConn.WriteMessage(websocket.TextMessage, senderBytes)
			if err != nil {
				return
			}
		}
	}
}

// ChatWithUid 单聊Uid
func (c *ChatController) ChatWithUid(wsConn *websocket.Conn, userId int64) {
	defer func(wsConn *websocket.Conn) {
		wsConn.CloseHandler()
	}(wsConn)
	// 聊天监听处理
	for {
		// bytes 缓存读取数据
		msg := make([]byte, 512)
		pointMsg := new(SenderMsg)
		_, msg, err := wsConn.ReadMessage()
		if err != nil {
			return
		}
		// 数据解析到结构体
		err = json.Unmarshal(msg, pointMsg)
		pointMsg.Sender = userId
		// 请求格式错误处理
		if err != nil {
			senderMsg := new(SenderMsg)
			senderMsg.Sender = userId
			senderMsg.Receptor = pointMsg.Receptor
			senderMsg.Msg = "Request Data Format Is Wrong"
			senderMsg.MsgType = "notice"
			// 结构体解析成bytes数据
			senderBytes, err := json.Marshal(senderMsg)
			if err != nil {
				return
			}
			// 解析失败
			err = wsConn.WriteMessage(websocket.TextMessage, senderBytes)
			if err != nil {
				return
			}
			continue
		}
		reWsConn, ok := Hub[pointMsg.Receptor]
		// 用户未在线处理
		if !ok {
			senderMsg := new(SenderMsg)
			senderMsg.Sender = userId
			senderMsg.Receptor = pointMsg.Receptor
			senderMsg.Msg = "This User Is Not Online,Auto Save to Queue"
			senderMsg.MsgType = "notice"
			// 存入消息队列
			MessageQueues[pointMsg.Receptor] = append(MessageQueues[pointMsg.Receptor], pointMsg)
			// 结构体解析成bytes数据
			senderBytes, err := json.Marshal(senderMsg)
			if err != nil {
				return
			}
			err = wsConn.WriteMessage(websocket.TextMessage, senderBytes)
			if err != nil {
				return
			}
			continue
		}
		// 解析结构体
		senderBytes, err := json.Marshal(pointMsg)
		if err != nil {
			return
		}
		// 发送数据
		err = reWsConn.WriteMessage(websocket.TextMessage, senderBytes)
		if err != nil {
			return
		}
	}

}

//func (c *ChatController) _writeMessage(wsConn *websocket.Conn,)  {
//
//}

// BroadcastMessage 广播
//func (c *ChatController) BroadcastMessage(gc *gin.Context) {
//
//}
